﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using JXPlatform.Infrastructure.Interfaces.GIS;
using JXPlatform.GIS.Models;
using Microsoft.Practices.Prism.Commands;
using Microsoft.Practices.Prism.ViewModel;
using System.Collections.ObjectModel;
using System.ComponentModel.Composition;

namespace JXPlatform.GIS.ViewModels
{
    [Export]
    public class PointListViewModel : NotificationObject
    {
        private readonly IPointService _pointService;

        [ImportingConstructor]
        public PointListViewModel(IPointService pointService)
        {
            if (pointService == null)
            {
                throw new ArgumentNullException("pointService");
            }

            _pointService = pointService;
            PointListItems = new ObservableCollection<PointViewModel>();
            SelectedPointItems = new ObservableCollection<PointViewModel>();

            InitCommands();
            PopulatePointListItems(_pointService.GetPoints());
        }

        private void InitCommands()
        {
            AddCommand = new DelegateCommand<object>(OnAddCommand);
            RemoveCommand = new DelegateCommand<object>(OnRemoveCommand);
            CopyCommand = new DelegateCommand<object>(OnCopyCommand);
            ParseCommand = new DelegateCommand<object>(OnParseCommand);
        }

        private void OnParseCommand(object obj)
        {
            var txt = Clipboard.GetText();
            if (string.IsNullOrWhiteSpace(txt))
            {
                return;
            }

            SelectedPointItems.Clear();

            var index = FocusedPointItem == null ? 0 : PointListItems.IndexOf(FocusedPointItem) + 1;
            var m = Regex.Match(txt, @"(?<x>\d.)\D(?<y>\d.)");
            while (m.Success)
            {
                var point = _pointService.CreatePoint();
                point.X = double.Parse(m.Groups["x"].ToString());
                point.Y = double.Parse(m.Groups["y"].ToString());

                var pointViewModel = new PointViewModel(_pointService, point);
                PointListItems.Insert(index++, pointViewModel);
                SelectedPointItems.Add(pointViewModel);

                m = m.NextMatch();
            }
        }

        private void OnCopyCommand(object obj)
        {
            var sb = new StringBuilder();
            foreach (PointViewModel selectedPointItem in SelectedPointItems)
            {
                sb.Append(string.Format("{0}\t{1}\r\n", selectedPointItem.X, selectedPointItem.Y));
            }

            Clipboard.SetText(sb.ToString());
        }

        private void OnRemoveCommand(object obj)
        {
            while (SelectedPointItems.Count > 0)
            {
                var pointViewModel = SelectedPointItems[0];
                PointListItems.Remove(pointViewModel);
            }

            SelectedPointItems.Clear();
        }

        private void OnAddCommand(object obj)
        {
            var pointViewModel = new PointViewModel(_pointService, _pointService.CreatePoint());
            PointListItems.Add(pointViewModel);

            FocusedPointItem = pointViewModel;
        }

        private ObservableCollection<PointViewModel> _pointListItems;
        public ObservableCollection<PointViewModel> PointListItems
        {
            get { return _pointListItems; }
            private set
            {
                if (_pointListItems != value)
                {
                    _pointListItems = value;
                    RaisePropertyChanged(()=>PointListItems);
                }
            }
        }

        private void PopulatePointListItems(IEnumerable<IPoint> points)
        {
            foreach (var point in points)
            {
                var pointViewModel = new PointViewModel(_pointService, point);
                PointListItems.Add(pointViewModel);
            }
        }

        public ICommand AddCommand { get; private set; }
        public ICommand RemoveCommand { get; private set; }
        public ICommand CopyCommand { get; private set; }
        public ICommand ParseCommand { get; private set; }

        private PointViewModel _focusedPointItem;
        public PointViewModel FocusedPointItem
        {
            get { return _focusedPointItem; }
            set
            {
                _focusedPointItem = value;
                RaisePropertyChanged(()=>FocusedPointItem);
            }
        }

        private ObservableCollection<PointViewModel> _selectedPointItems; 
        public ObservableCollection<PointViewModel> SelectedPointItems
        {
            get { return _selectedPointItems; }
            private set
            {
                _selectedPointItems = value;
                RaisePropertyChanged(() => SelectedPointItems);
            }
        }  
    }
}
